Kapitel 24 Programmiertechniken
Sie erhalten im Folgenden eine umfassende Einführung in verschiedene Programmiertechniken.
24.1 Drag & Drop-Operationen
 
Drag & Drop gehört zu den fundamentalsten Techniken der Windows-Betriebssysteme. Damit wird es einem Anwender ermöglicht, ein Objekt zu markieren und es bei gedrückter Maustaste an eine andere Stelle zu ziehen. Der Empfänger kann sich sowohl in derselben als auch in einer anderen Anwendung befinden. Unterstützend erhält der Anwender während des Ziehvorgangs ein visuelles Feedback, wenn sich der Mauszeiger über einer Komponente befindet, die in der Lage ist, das gezogene Objekt aufzunehmen. Diese Technik wird beispielsweise im Windows Explorer sehr gerne dazu benutzt, eine oder mehrere Dateien in ein anderes Verzeichnis zu verschieben oder zu kopieren.
Bei Drag & Drop-Vorgängen spielen immer zwei Elemente eine Rolle: die Quelle, aus der ein Objekt gezogen wird, und der Empfänger, der das Objekt entgegennimmt. Beim Kopieren erhält der Empfänger eine Kopie des Objekts, beim Verschieben wird das Objekt in der Quelle gelöscht, und bei einer Verknüpfungsoperation verweisen sowohl Quelle als auch Ziel auf dasselbe Objekt.
In Abhängigkeit vom Status der Umschalttasten wird entschieden, ob eine Operation ein Objekt kopiert, verschiebt oder auch nur verknüpft. Wird keine Taste gedrückt, handelt es sich üblicherweise um eine Verschiebeoperation, ist die (Strg)-Taste während des Vorgangs gedrückt, wird kopiert, und die Kombination aus (Umschalttaste) und (Strg)-Taste bewirkt das Verknüpfen.
24.1.1 Der Ablauf einer Drag & Drop-Operation
 
Normalerweise werden Drag & Drop-Operationen als Reaktion auf das MouseDown-Ereignis ausgelöst. Meistens handelt es sich dabei um die linke Maustaste, in manchen Anwendungen sind aber auch Operationen über die rechte möglich. Um eine Drag & Drop-Operation einzuleiten, wird im Ereignishandler die Methode DoDragDrop des Startelements aufgerufen.
Nicht jede Komponente ist automatisch ein potenzieller Empfänger der Drag & Drop-Operation. Vielmehr müssen die Komponenten, die als Empfänger in Frage kommen, die Eigenschaft AllowDrop=true eingestellt haben.
In Verbindung mit dem Ziehvorgang treten mehrere Ereignisse auf. Die beiden wichtigsten sind DragEnter und DragDrop. Da mit Drag & Drop die verschiedensten Datenformate bewegt werden können (Zeichenfolgen, Dateien, Images usw.), muss jeder potenzielle Empfänger einer Drag & Drop-Operation überprüfen, ob er das aktuell gezogene Datenformat überhaupt aufnehmen kann. Das passiert im Ereignis DragEnter. Das Ablegen des gezogenen Objekts erfolgt dann im Ereignis DragDrop.
24.1.2 Das Einleiten einer Drag & Drop-Operation
 
Um die Drag & Drop-Operation auszulösen, ist der Aufruf der Methode DoDragDrop notwendig, der im ersten Parameter das zu kopierende oder zu verschiebende Objekt übergeben wird. Der zweite Parameter vom Typ DragDropEffects beschreibt, welche Operationen mit dem Objekt möglich sind.
| public DragDropEffects DoDragDrop(object, DragDropEffects);
|
Die Methode befindet sich so lange in der Ausführung, bis die Operation abgeschlossen ist. Der Rückgabewert der Methode beschreibt, wie der Empfänger die Daten entgegengenommen hat. In den meisten Fällen werden Sie aber den Rückgabewert vermutlich ignorieren können.
Die Mitglieder der Enumeration DragDropEffects können bitweise verknüpft werden, um mit einem Methodenaufruf mehrere verschiedene Operationen zu erlauben.
Tabelle 24.1 Die Enumeration »DragDropEffects«
| Mitglied
|
Beschreibung
|
| None
|
Die Daten werden vom Ziel nicht akzeptiert.
|
| Copy
|
Die Daten werden in das Ziel kopiert.
|
| Move
|
Die Daten aus der Quelle werden in das Ziel verschoben.
|
| Link
|
Die Daten aus der Quelle werden mit dem Ziel verknüpft.
|
| Scroll
|
Der Bildlauf wird begonnen oder momentan im Ziel durchgeführt.
|
| All
|
Die Daten werden kopiert, aus der Quelle entfernt und über einen Bildlauf im Ablageziel abgelegt.
|
So einfach im ersten Moment das Einleiten einer Drag & Drop-Operation erscheinen mag, so schwierig kann es sich bei der Programmierung erweisen. Der Grund dafür ist, dass einige Steuerelemente bei einem Click-Ereignis eine Standardreaktion zeigen. Die Problematik ist, zwischen dem Standardverhalten und der Drag & Drop-Operation zu unterscheiden.
24.1.3 Die Ereignisse des Empfängers einer Drag & Drop-Operation
 
Der Empfänger muss auch als ein solcher konfiguriert sein, standardmäßig ist das nämlich nicht der Fall. Ein Drag & Drop-Empfänger wird erst zu einem solchen, wenn die von der Klasse Control geerbte Eigenschaft AllowDrop auf true festgelegt ist und die Komponente damit ihre Empfangsbereitschaft signalisiert.
| public virtual bool AllowDrop {get; set;}
|
Bei einer als Empfänger registrierten Komponente spielen insgesamt vier Ereignisse eine Rolle: DragEnter, DragOver, DragDrop und DragLeave.
| public event DragEventHandler DragEnter;
|
| public event DragEventHandler DragOver;
|
| public event DragEventHandler DragDrop;
|
| public event EventHandler DragLeave;
|
Machen wir uns zunächst deutlich, unter welchen Umständen die Ereignisse ausgelöst werden.
|
Das Ereignis DragEnter wird ausgelöst, wenn der Mauszeiger in den Bereich eines Drag & Drop-Empfängers eindringt. Dabei kann es sich um eine Form oder um ein Steuerelement handeln. Das Ereignis wird dazu benutzt, um zu prüfen, ob das betreffende Steuerelement in der Lage ist, das Datenformat des gezogenen Objekts aufzunehmen. Ist das nicht der Fall, wird ein Symbol angezeigt, das an ein Verbotsschild erinnert. Dieses Symbol hat noch einer weiter reichende Konsequenz. Solange nämlich dieses Symbol angezeigt wird, tritt auch kein DragDrop-Ereignis auf, wenn der Anwender die Maustaste loslässt. Die Daten werden dann nicht fallen gelassen. |
|
DragOver ist mit dem Ereignis MouseOver vergleichbar und tritt kontinuierlich auf, während die Maus über die Komponente bewegt wird. Dabei wird die Darstellung des Cursors abhängig davon, ob es sich um einen Verschiebe- oder Kopiervorgang handelt, geändert. Im Windows Explorer beispielsweise wird der Cursor bei einer Verschiebeoperation durch einen Pfeil gekennzeichnet, beim Kopieren durch ein zusätzliches »+«-Zeichen am rechten unteren Ende des Pfeils. Über einem Element, das kein Empfänger einer Drag & Drop-Operation ist, wird sich der Mauszeiger nicht ändern und stattdessen einen Kreis mit dem schrägen roten Balken anzeigen. |
|
Wird die gedrückte Maustaste über dem Empfänger losgelassen, kommt es zum DragDrop-Ereignis, und das Objekt wird abgelegt. Wie das losgelassene Objekt im Empfänger behandelt wird, hängt von den Anforderungen ab. |
|
Wird mit gedrückter Maustaste der Bereich eines möglichen Empfängers verlassen, wird dessen Ereignis DragLeave ausgelöst. Nur in wenigen Fällen werden Sie einen Ereignishandler benötigen, um beim Verlassen des Empfängers eine Operation auszuführen. |
Die Parameterliste der Ereignishandler
Das Ereignis DragLeave wird von einem EventArgs-Objekt begleitet, das uns schon oft begegnet ist und von dem wir wissen, dass es keine ereignisrelevanten Daten liefert. Daher können wir auf eine weitergehende Beschreibung verzichten.
Anders sieht es bei den drei Ereignissen DragEnter, DragDrop und DragOver aus. Die Ereignishandler dieser Ereignisse empfangen ein Objekt vom DragEventArgs, das ein Reihe von Eigenschaften bereitstellt, um genauere und verwertbare Informationen über die laufende Operation zu liefern.
Tabelle 24.2 Eigenschaften des »DragEventArgs«-Objekts
| Eigenschaft
|
Beschreibung
|
| AllowEffected
|
Diese Eigenschaft ist schreibgeschützt und beschreibt die Optionen, die dem Empfänger von der Quelle zur Verfügung gestellt werden (Kopieren, Verschieben oder Verknüpfen). Damit enthält diese Eigenschaft die Kombination von DragDropEffects, die beim Aufruf der Methode DoDragDrop dem zweiten Parameter übergeben worden sind.
|
| Data
|
Enthält die dem Ereignis zugeordneten Daten. Die Daten sind vom Typ IDataObject.
|
| Effect
|
Diese Eigenschaft, die ebenfalls vom Typ DragDropEffects ist, legt die Optionen des Drag & Drop-Vorgangs und somit auch das Aussehen der Maus für den Empfänger fest. Effect muss insbesondere im Ereignishandler von DragEnter eingestellt werden, da ansonsten ein Mauscursor dargestellt wird, der symbolisiert, dass kein DragDrop-Ereignis ausgelöst wird. Eingestellt werden dürfen aber nur Werte, die auch unter AllowEffected angegeben sind.
|
| KeyState
|
Ruft den aktuellen Zustand von (Umschalttaste), (Strg), (Alt) sowie den Zustand der Maustasten ab (siehe auch Tabelle 24.3).
|
| X, Y
|
Ruft die x- bzw. y-Koordinate des Mauszeigers in Bildschirmkoordinaten ab.
|
| Hinweis Die gezogenen Daten liegen während einer Drag & Drop-Operation im Format IDataObject vor. Diesen Typ mit seinen Methoden wie beispielsweise GetDataPresent und GetFormats hatten wir im Zusammenhang mit der Programmierung der Zwischenablage in Kapitel 18.4 bereits besprochen.
|
Beachten Sie bitte, dass X und Y die Koordinaten des Mauszeigers auf dem Bildschirm liefern. Diese Werte sind normalerweise wertlos, können aber relativ einfach in die Koordinaten eines Steuerelements umgerechnet werden. Dabei hilft die PointToClient-Methode weiter, die auf das erforderliche Steuerelement aufgerufen wird:
| Point pt = Steuerelement.PointToClient(this.MousePosition);
|
Die Eigenschaft KeyState ist folgendermaßen definiert:
| public int KeyState {get;}
|
Diese Eigenschaft verwendet erstaunlicherweise nicht wie ansonsten üblich eine Enumeration, sondern beschreibt den Zustand aller in Frage kommenden Tasten über einen Integer. Da KeyState mit dem Flags-Attribut verknüpft ist, wird der Rückgabewert der Eigenschaft bitweise interpretiert.
Tabelle 24.3 Die Bitflags der Eigenschaft »KeyState«
| Bitflag
|
Taste
|
| 1
|
linke Maustaste
|
| 2
|
rechte Maustaste
|
| 4
|
(Shift)-Taste
|
| 8
|
(Strg)-Taste
|
| 16
|
mittlere Maustaste
|
| 32
|
(Alt)-Taste
|
Das »QueryContinueDrag«-Ereignis der Ereignisquelle
Für das Steuerelement, das für die Drag & Drop-Operation als Quelle verantwortlich ist, werden permanent die QueryContinueDrag-Ereignisse ausgelöst. Das Ereignis bietet sich insbesondere an, um einen eingeleiteten Vorgang vorzeitig abzubrechen und dabei festzulegen, was mit dem gezogenen Objekt passieren soll.
Das Ereignis schickt an seinen Ereignishandler ein Objekt vom Typ QueryContinueDragEventArgs. Dieses hat drei Eigenschaften:
|
Action |
|
EscapePressed |
|
KeyState |
KeyState teilt mit, welche Tasten während der Operation gedrückt sind (siehe Tabelle 24.3), EscapePressed ruft ab, ob der Anwernder die (ESC)-Taste gedrückt hat.
Mit Action lässt sich der Status der andauernden Operation bestimmen und beeinflussen. Diese Eigenschaft ist vom Typ der Enumeration DragAction, mit welcher der Fortgang der Operation festgelegt werden kann.
Tabelle 24.4 Die Enumeration »DragAction«
| Member
|
Beschreibung
|
| Cancel
|
Die Operation wird abgebrochen. Dabei werden die Daten nicht abgelegt.
|
| Continue
|
Die Operation wird fortgesetzt.
|
| Drop
|
Die Operation wird beendet. Dabei werden die Daten abgelegt.
|
24.1.4 Programmbeispiele
 
An den folgenden vier Beispielen wollen wir uns nun ansehen, wie Drag & Drop realisiert werden kann. Im ersten Beispiel wird nur eine einfache Operation zwischen zwei Textboxen gezeigt, im zweiten eine Operation, bei der zwischen zwei Pictureboxen ein Bildchen hin- und hergeschoben/kopiert wird. Drag & Drop zwischen zwei Listboxen ist nur unter erheblichem Programmieraufwand möglich, wenn die Listboxen eine Mehrfachauswahl zulassen. Das dritte Beispiel stellt dazu eine gleichwertige Alternative vor, die anstelle von Listboxen ListView-Steuerelemente benutzt. Im letzten Beispiel wird Ihnen abschließend noch gezeigt, wie Dateien bei einer Drag & Drop-Operation behandelt werden.
Drag & Drop zwischen zwei Textboxen
Die Form des folgenden Beispiels enthält die beiden Textboxen textBox1 und textBox2. Der Inhalt von textBox1 soll mittels Drag & Drop in die textBox2 verschoben oder kopiert werden. Zum Kopieren muss während des Ziehvorgangs die (Strg)-Taste gedrückt sein. Die Eigenschaft AllowDrop von textBox2 ist auf true eingestellt.
| // -------------------------------------------------------------
|
| // Beispiel: ...\Kapitel 24\DragAndDrop_Textboxen
|
| // -------------------------------------------------------------
|
| private void textBox1_MouseDown(object sender, MouseEventArgs e) {
|
| textBox1.DoDragDrop(textBox1.Text,
|
| DragDropEffects.Copy | DragDropEffects.Move);
|
| }
|
| private void textBox2_DragEnter(object sender, DragEventArgs e) {
|
| if(e.Data.GetDataPresent(DataFormats.Text))
|
| // wenn die Strg-Taste gedrückt ist
|
| if((e.KeyState & 8) == 8)
|
| e.Effect = DragDropEffects.Copy;
|
| // wenn nur die linke Maustaste gedrückt ist
|
| else
|
| e.Effect = DragDropEffects.Move;
|
| else
|
| e.Effect = DragDropEffects.None;
|
| }
|
| private void textBox2_DragDrop(object sender, DragEventArgs e) {
|
| textBox2.Text = e.Data.GetData(DataFormats.Text).ToString();
|
| if((e.KeyState & 8) != 8)
|
| textBox1.Clear();
|
| }
|
Eingeleitet wird die Drag & Drop-Operation mit dem Drücken der linken Maustaste im Textfeld textBox1. Dabei wird die Methode DoDragDrop aufgerufen, der im ersten Argument die zu erfassenden Daten mitgeteilt werden. Hier ist es der gesamte Inhalt von textBox1. Im zweiten Argument ist festgelegt, dass die Daten sowohl verschoben als auch kopiert werden können.
| textBox1.DoDragDrop(textBox1.Text,
|
| DragDropEffects.Copy | DragDropEffects.Move);
|
Dringt der Mauszeiger bei gleichzeitig gedrückter linker Maustaste in den Bereich des Objekts textBox2 ein, wird das Ereignis DragEnter ausgelöst. Wir benutzen den Ereignishandler dazu, um zunächst einmal festzustellen, ob die von der aktuellen Drag & Drop-Operation erfassten Daten auch im Textformat vorliegen. Theoretisch wäre es auch möglich, dass aus einer anderen Quelle heraus Daten verschoben werden, die nicht im Text-, sondern zum Beispiel im Bildformat vorliegen. Dann darf die Textbox natürlich auch nicht mit einem Symbol ihre Bereitschaft signalisieren, die Daten aufnehmen zu können.
Verläuft die Überprüfung in DragEnter mit
| if(e.Data.GetDataPresent(DataFormats.Text))
|
positiv, gilt es festzustellen, ob die (Strg)-Taste gedrückt ist oder nicht. Ist diese Zustandstaste gedrückt, werden die Daten – falls sie in der Textbox textBox2 fallen gelassen werden – kopiert, andernfalls nur verschoben. Das dazugehörige Symbol wird durch die Übergabe einer DragDropEffects-Konstanten an die Eigenschaft Effects festgelegt, beispielsweise:
| if((e.KeyState & 8) == 8)
|
| e.Effect = DragDropEffects.Copy;
|
| Die Zuweisung an Effect hat noch einen weiteren, sehr wichtigen Hintergrund, der zu erkennen ist, wenn man den Code in DragEnter auskommentiert: Es ist dann keine Drop-Operation mehr möglich. Als Symbol wird in diesem Fall nur noch ein Kreis mit einem schrägen Balken angezeigt. In DragEnter wird also folglich die Bereitschaft der Komponte festgelegt, die Daten zu empfangen, und darüber hinaus auch, wie die Daten behandelt werden.
|
Wird die Maustaste losgelassen, während sich der Mauszeiger über textBox2 befindet, kommt es zum Ereignis DragDrop. Hier werden die Daten nach vorhergehender Konvertierung in den Typ string in das Objekt textBox2 geschrieben. Außerdem muss überprüft werden, ob es sich um eine Verschiebe- oder Kopieroperation handelt. Im ersteren Fall gilt es, die verschobenen Daten in der Quelle zu löschen.
Da Drag & Drop auch anwendungsübergreifend funktioniert, können Sie aus einem beliebigen textbasierten Dokument heraus Daten verschieben. Andererseits wird das Verschieben beispielsweise einer Bitmap-Datei von der Textbox im Beispielprogramm ignoriert.
Drag & Drop zwischen zwei Pictureboxen
Genauso einfach wie das Verschieben einer Zeichenfolge ist das Verschieben eines Bildes. Der Code unterscheidet sich nur geringfügig, da nur der abweichende Datentyp zu beachten ist.
Im folgenden Beispiel enthält die Form zwei Pictureboxen. Nach dem Start enthält die mit pic1 bezeichnete Picturebox ein Bild, das in die mit pic2 bezeichnete Picturebox entweder verschoben oder kopiert werden kann. Weil es nur geringfügig mehr Codierungsaufwand bedeutet, ist in diesem Beispiel die Drag & Drop-Operation in beide Richtungen möglich. Dazu werden die Ereignisse MouseDown, DragEnter und DragDrop mit dem gleichen Ereignishandler verknüpft. Im DragDrop-Ereignishandler ist für den Fall, dass eine Verschiebeoperation vorliegt, in der richtigen Quelle das Bild zu löschen. Dazu ist die Referenz des sender-Parameters zu überprüfen.
| Hinweis Die Eigenschaft AllowDrop der Pictureboxen muss natürlich auf true gesetzt werden. Im Eigenschaftsfenster wird diese Eigenschaft aber aus unerklärlichen Gründen nicht aufgelistet. Sie müssen also eine entsprechende Anweisung codieren. Dabei werden Sie feststellen, dass AllowDrop auch nicht in der IntelliSense-Liste zu finden ist. Setzen Sie sich darüber einfach hinweg.
|
| // -------------------------------------------------------------
|
| // Beispiel: ...\Kapitel 24\DragAndDrop_Bilddateien
|
| // -------------------------------------------------------------
|
| private void Form1_Load(object sender, EventArgs e) {
|
| pic1.AllowDrop = true;
|
| pic2.AllowDrop = true;
|
| }
|
| private void InitializeComponent() {
|
| pic1.DragEnter += new DragEventHandler(pic_DragEnter);
|
| pic1.DragDrop += new DragEventHandler(pic_DragDrop);
|
| pic1.MouseDown += new MouseEventHandler(pic_MouseDown);
|
| pic2.DragEnter += new DragEventHandler(pic_DragEnter);
|
| pic2.DragDrop += new DragEventHandler(pic_DragDrop);
|
| pic2.MouseDown += new MouseEventHandler(pic_MouseDown);
|
| }
|
| private void pic_MouseDown(object sender, MouseEventArgs e) {
|
| PictureBox pic = (PictureBox)sender;
|
| // wenn ein Bild angezeigt wird, die Drag & Drop-Operation
|
| // einleiten
|
| if(pic.Image != null)
|
| pic.DoDragDrop(pic.Image,
|
| DragDropEffects.Copy | DragDropEffects.Move);
|
| }
|
| private void pic_DragEnter(object sender, DragEventArgs e) {
|
| if(e.Data.GetDataPresent(DataFormats.Bitmap))
|
| // wenn die Strg-Taste gedrückt ist
|
| if((e.KeyState & 8) == 8)
|
| e.Effect = DragDropEffects.Copy;
|
| // wenn nur die linke Maustaste gedrückt ist
|
| else
|
| e.Effect = DragDropEffects.Move;
|
| else
|
| e.Effect = DragDropEffects.None;
|
| }
|
| private void pic_DragDrop(object sender, DragEventArgs e) {
|
| PictureBox pic = (PictureBox)sender;
|
| // die empfangenen Daten in den Typ Image konvertieren
|
| pic.Image = (Image)e.Data.GetData(DataFormats.Bitmap);
|
| if((e.KeyState & 8) != 8)
|
| if(pic == pic1)
|
| pic2.Image = null;
|
| else
|
| pic1.Image = null;
|
| }
|
Drag & Drop zwischen Listen
Wenn Sie die Elemente zwischen zwei Listen mit Drag & Drop verschieben oder kopieren wollen, wird es etwas schwieriger. Normalerweise werden Sie sich bei einer Liste für den Typ ListBox entscheiden, der jedoch Probleme bereitet, wenn mehrere Listenelemente an der Operation teilnehmen sollen. In solchen Fällen ist der Typ ListView empfehlenswerter.
Das Steuerelement ListView hat, ebenso wie auch TreeView, ein zusätzliches Ereignis, mit dem das Ziehen eines oder mehrerer Elemente erleichtert wird: ItemDrag. Dieses Ereignis tritt auf, wenn zur Laufzeit mit dem Ziehen begonnen wird. Über die Eigenschaften des Args-Parameters kann man die bei dem Vorgang gedrückte Maustaste sowie das zu ziehende Element ermitteln, aber meistens wird der Ereignishandler nur dazu benutzt, die Methode DoDragDrop aufzurufen.
Im folgenden Beispielprogramm können die Listenelemente von zwei ListView-Objekten beliebig verschoben werden. Die Form enthält zwei dieser Steuerelemente, deren AllowDrop-Eigenschaft selbstverständlich wieder auf true gesetzt ist. Da standardmäßig nur eine einfache Auswahl möglich ist, sollte die Mehrfachauswahl mit der Eigenschaft MultiSelect eingestellt werden. Um die Listbox zu simulieren, ist View=List gewählt, aber es kann natürlich auch aus den anderen angebotenen Ansichten heraus verschoben werden.
Sehen wir uns zuerst den Code des ItemDrag-Ereignishandlers an, der mit beiden Listenansichten verknüpft ist.
| private void ListView_ItemDrag(object sender, ItemDragEventArgs e) {
|
| ListView listview = (ListView)sender;
|
| ListViewItem[] items = new ListViewItem[listview.SelectedItems.Count];
|
| for(int i = 0; i < listview.SelectedItems.Count; i++)
|
| items[i] = listview.SelectedItems[i];
|
| listview.DoDragDrop(new DataObject("ListViewItemData", items),
|
| DragDropEffects.Move);
|
| }
|
Zuerst wird ein Array vom Typ ListViewItem deklariert, das anschließend mit den ausgewählten Listenelementen aus der SelectedListViewItemCollection der Listenansicht gefüllt wird. Beim Aufruf der DoDragDrop-Methode müssen zuerst die an der Operation beteiligten Daten bekannt gegeben werden. Damit auch wirklich nur die dafür vorgesehene Listenansicht die Daten empfangen kann, spezifizieren wir ein eigenes DataObject. Dazu übergeben wir dem Konstruktor zuerst einen beliebigen Bezeichner für die zu verschiebenden Daten, anschließend die Daten selbst. Als Operation ist in diesem Beispiel nur das Verschieben vorgesehen.
Im Drag & Drop-Empfänger wird zuerst das Ereignis DragEnter ausgelöst. In diesem werden die gezogenen Daten einer Typuntersuchung unterzogen. Hier fragen wir nach dem Bezeichner, den wir DataObject-Konstruktor genannt haben. Sind die Daten vom Typ ListViewItemData, kann der Verschiebevorgang initialisiert werden.
| private void listView_DragEnter(object sender, DragEventArgs e) {
|
| if(e.Data.GetDataPresent("ListViewItemData"))
|
| e.Effect = DragDropEffects.Move;
|
| else
|
| e.Effect = DragDropEffects.None;
|
| }
|
Dem Fallenlassen der gezogenen Daten und dem damit ausgelösten Ereignis DragDrop kommt jetzt nur noch die Aufgabe zu, den Empfänger mit den gezogenen Listenelementen zu füllen und diese gleichzeitig in der Quelle zu löschen.
| private void listView_DragDrop(object sender, DragEventArgs e) {
|
| ListView listview = (ListView)sender;
|
| ListViewItem[] items = (ListViewItem[])(e.Data.GetData("ListViewItemData"));
|
| for(int i = 0; i < items.Length; i++) {
|
| listview.Items.Add(items[i].Text);
|
| if(listview == listView1)
|
| listView2.Items.Remove(listView2.SelectedItems[0]);
|
| else
|
| listView1.Items.Remove(listView1.SelectedItems[0]);
|
| }
|
Den vollständigen Code zu diesem Beispiel finden Sie auf der Buch-CD unter \Kapitel 24\DragAndDrop_Listen.
Drag & Drop von Dateien
Das letzte Beispielprogramm soll Ihnen demonstrieren, wie Dateien gezogen werden – hier im Besonderen Dateien mit Textinhalt, aber grundsätzlich können Sie auf diese Weise mit jedem Dateityp verfahren. Die Dateien können beispielsweise aus dem Windows Explorer in die Textbox der Form gezogen werden. Der Dateiinhalt wird dabei in der Textbox angezeigt.
Das Datenformat von Dateien, die an einer Drag & Drop-Operation teilnehmen, wird durch das Feld FileDrop der Klasse DataFormat beschrieben. Der Rückgabewert der Methode GetData ist dann die Zeichenfolge, die den Zugriffspfad auf die gezogene Datei beschreibt. Da es im Windows Explorer auch möglich ist, mehrere Dateien zu ziehen, könnte es sich auch um ein Array handeln, das in ein Zeichenfolge-Array konvertiert werden muss.
Das Array wird in einer Schleife Element für Element durchlaufen. Nach einer Überprüfung der Dateierweiterung (es sind nur Dateien mit den Endungen TXT, INI und LOG zugelassen) wird die sich jeweils im Zugriff befindliche Datei geöffnet und im Fenster angezeigt.
| // -------------------------------------------------------------
|
| // Beispiel: ...\Kapitel 24\DragAndDrop_Dateien
|
| // -------------------------------------------------------------
|
| private void textBox1_DragDrop(object sender, DragEventArgs e) {
|
| if(e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
| // liefert in einem Array alle im Explorer ausgewählten Dateien
|
| string[] strFileName = (string[])e.Data.GetData(DataFormats.FileDrop);
|
| StreamReader sr;
|
| // alle ausgewählten Dateien in der Textbox anzeigen
|
| for(int i = 0; i < strFileName.Length; i++) {
|
| try {
|
| // nur TXT-, LOG- und INI-Dateien einlesen
|
| if(Path.GetExtension(strFileName[i]) == ".txt" ||
|
| Path.GetExtension(strFileName[i]) == ".log" ||
|
| Path.GetExtension(strFileName[i]) == ".ini")
|
| sr = new StreamReader(strFileName[i]);
|
| else
|
| continue;
|
| }
|
| catch (IOException ex) {
|
| MessageBox.Show(ex.Message);
|
| return;
|
| }
|
| textBox1.Text += new string('=', 60) + "\r\n";
|
| textBox1.Text += "Datei: " + strFileName[i] + "\r\n";
|
| textBox1.Text += new string('=', 60) + "\r\n";
|
| textBox1.Text += sr.ReadToEnd() + "\r\n";
|
| sr.Close();
|
| }
|
| }
|
| }
|
| private void textBox1_DragEnter(object sender, DragEventArgs e) {
|
| if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
| e.Effect = DragDropEffects.Link;
|
| else
|
| e.Effect = DragDropEffects.None;
|
| }
|
|